package com.roy.nio.groupChat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * @author ：楼兰
 * @date ：Created in 2021/6/4
 * @description:
 **/

public class ChatServer {
    public static void main(String[] args) throws IOException {
        final ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        final Selector selector = Selector.open();
        serverSocketChannel.bind(new InetSocketAddress(8080));
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("服务器启动成功");
        while (true){
            final int select = selector.select();
            if(select < 1){
                System.out.println("当前没有连接进来");
                continue;
            }
            final Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()){
                final SelectionKey key = iterator.next();
                if(key.isValid() && key.isAcceptable()){
                    final SocketChannel newSocketChannel = serverSocketChannel.accept();
                    System.out.println("收到客户端的连接请求:"+newSocketChannel.getRemoteAddress());
                    newSocketChannel.configureBlocking(false);
                    newSocketChannel.register(selector, SelectionKey.OP_READ);
                    System.out.println("当前在线人数："+selector.keys().size());
                }
                if(key.isValid() && key.isReadable()){
                    System.out.println("收到客户端的消息请求。");
                    handleKey(selector,key);
                }
            }
            iterator.remove();
        }
    }
    //其他地方基本都是模版，唯一需要定制的就是这个方法。
    private static void handleKey(Selector selector,SelectionKey key){
        final SocketChannel senderChannel = (SocketChannel)key.channel();
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        try{
            //获取到客户端发过来的消息。
            senderChannel.read(byteBuffer);
            String message = new String(byteBuffer.array());
            String clientAddr = senderChannel.getRemoteAddress().toString();
            System.out.println(clientAddr+"发送消息:"+message);
            String response = "你 对大家说："+message;
            senderChannel.write(ByteBuffer.wrap(response.getBytes()));

            final Set<SelectionKey> selectionKeys = selector.keys();
            final Iterator<SelectionKey> iter = selectionKeys.iterator();
            while(iter.hasNext()){
                final SelectionKey clientKey = iter.next();
                final SelectableChannel clientChannel = clientKey.channel();
                if(clientChannel instanceof SocketChannel && clientChannel != senderChannel) {
                    SocketChannel clientSocketChannel = (SocketChannel) clientChannel;
                    //对消息发送者
                    response = clientSocketChannel.getRemoteAddress().toString()+ " 跟大家说：" + message;
                    clientSocketChannel.write(ByteBuffer.wrap(response.getBytes()));
                }
            }
        }catch (IOException e){
            try {
                System.out.println("客户端断开连接："+senderChannel.getRemoteAddress());
                key.cancel();
                senderChannel.socket().close();
                senderChannel.close();
            } catch (IOException ioException) {
            }
        }

    }
}
